home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / comm / msged400.zip / src / fido.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  19KB  |  694 lines

  1. /*
  2.  *  FIDO.C
  3.  *
  4.  *  Written on 30-Jul-90 by jim nutt.  Changes on 10-Jul-94 by John Dennis.
  5.  *  Released to the public domain.
  6.  *
  7.  *  Fido/Opus style message base support functions for Msged.
  8.  *
  9.  *  NOTE: These routines are slated for extinction in the near future.
  10.  *    They're to be replaced by the Squish msgAPI.  Possibly.
  11.  *
  12.  *  17-Dec-91  Added share support to all file routines and converted ANSI
  13.  *             file access code to low level read()/write().
  14.  *  26-Jan-92  Fixed bug in msg routines that seemed to cause a crash on
  15.  *             zero length msgs (zero, as in no ctrl info and text).
  16.  *  23-Feb-92  Removed locking routines.
  17.  *  01-Apr-92  Made New msgs remain open until writing the text, also added
  18.  *             some kludge code to handle the reading of Opus msgs.
  19.  *  12-Jul-92  Added some more functions to make the interface solid.
  20.  *  03-Dec-92  Fix to WriteHeader.
  21.  */
  22.  
  23. #define CHUNKSZ 256
  24. #define TEXTLEN 96
  25. #define NO_STDLIB               /* causes conflicts with errno.h with MSC */
  26.  
  27. #include <errno.h>
  28.  
  29. #include "msged.h"
  30. #include "date.h"
  31. #include "memextra.h"
  32.  
  33. #ifdef __MSC__
  34. #include <sys\locking.h>
  35. #endif
  36.  
  37. #if defined(PACIFIC)
  38. #include <unixio.h>
  39. #define O_WRONLY 0x0001
  40. #define O_BINARY 0x0000
  41. #define O_CREAT  0x0000
  42. #define O_RDWR   0x0002
  43. #define O_RDONLY 0x0000
  44. #define S_IREAD  0x0100
  45. #define S_IWRITE 0x0080
  46. #define EACCES   0x18
  47. #define EMFILE   0x19
  48. #define SH_DENYNO 0x40
  49. int sopen(char *filename, unsigned int access, int flags,...);
  50.  
  51. #elif defined(SASC)
  52. #define SH_DENYNO 0x40
  53. #define sopen(a,b,c,d) open(a,b)
  54. #include <fcntl.h>
  55.  
  56. #elif defined(UNIX)
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59. #include <unistd.h>
  60. #include <fcntl.h>
  61. #define sopen(a,b,c,d) open(a,b)
  62. #define O_BINARY 0x0000
  63.  
  64. #else
  65. #include <io.h>
  66. #include <sys\types.h>
  67. #include <sys\stat.h>
  68. #include <share.h>
  69. #include <fcntl.h>
  70. #endif
  71.  
  72. /* file access shortcuts */
  73.  
  74. #define OPENR   O_RDONLY|O_BINARY  /* open read-only */
  75. #define OPENC   O_WRONLY|O_BINARY|O_CREAT  /* open/create */
  76. #define OPENRW  O_RDWR|O_BINARY /* open read/write */
  77. #define S_IMODE S_IREAD|S_IWRITE  /* open mode */
  78.  
  79. /* prototypes */
  80.  
  81. #include "normal.h"
  82.  
  83. static int compare(const void *i, const void *j);
  84.  
  85. /* structures used in this module */
  86.  
  87. typedef struct _dosdate
  88. {
  89.     unsigned int day:5;
  90.     unsigned int mon:4;
  91.     unsigned int year:7;
  92.     unsigned int sec:5;
  93.     unsigned int min:6;
  94.     unsigned int hour:5;
  95. }
  96. DOSDATE;
  97.  
  98. static time_t dosdateToTimeT(DOSDATE * st);
  99.  
  100. typedef struct _fidoheader
  101. {
  102.     char from[36];              /* who from,             */
  103.     char to[36];                /* who to,               */
  104.     char subj[72];              /* message subject,      */
  105.     char date[20];              /* creation date,        */
  106.     unsigned char times[2];     /* number of times read, */
  107.     unsigned char dest[2];      /* destination node,     */
  108.     unsigned char orig[2];      /* originating node      */
  109.     unsigned char cost[2];      /* actual cost this msg  */
  110.     unsigned char orig_net[2];  /* originating net       */
  111.     unsigned char dest_net[2];  /* destination net       */
  112.     unsigned char written[4];   /* when it was written   */
  113.     unsigned char arrived[4];   /* when it arrived       */
  114.     unsigned char reply[2];     /* thread to previous msg */
  115.     unsigned char attrib[2];    /* message attributes */
  116.     unsigned char up[2];        /* thread to next msg    */
  117. }
  118. MFIDO;
  119.  
  120. /* local vars */
  121.  
  122. static int fp = -1;             /* current file handle */
  123. static unsigned long *msgarr = NULL;  /* array of *.msg numbers */
  124. static unsigned long msgarrsz = 0;  /* # of numbers in the array */
  125. static unsigned long oldsz = 0; /* total size of the array */
  126.  
  127. static void timet_to_char(time_t now, unsigned char arr[])
  128. {
  129.     struct tm *ts;
  130.     unsigned long x;
  131.  
  132.     ts = localtime(&now);
  133.     x = ts->tm_year - 80;
  134.     x = (x << 4) | (ts->tm_mon + 1);
  135.     x = (x << 5) | ts->tm_mday;
  136.     x = (x << 5) | ts->tm_hour;
  137.     x = (x << 6) | ts->tm_min;
  138.     x = (x << 5) | (ts->tm_sec / 2);
  139.     arr[0] = (unsigned char)((x >> 16) & 0xff);
  140.     arr[1] = (unsigned char)((x >> 24) & 0xff);
  141.     arr[2] = (unsigned char)(x & 0xff);
  142.     arr[3] = (unsigned char)((x >> 8) & 0xff);
  143. }
  144.  
  145. unsigned long FidoMsgnToUid(unsigned long n)
  146. {
  147.     if (n > msgarrsz || n == 0)
  148.         return 0;
  149.  
  150.     return msgarr[(size_t) (n - 1)];
  151. }
  152.  
  153. unsigned long FidoUidToMsgn(unsigned long n)
  154. {
  155.     unsigned long i;
  156.  
  157.     for (i = 0; i < msgarrsz; i++)
  158.         if (msgarr[(size_t) i] == n)
  159.             break;
  160.  
  161.     return (i == msgarrsz) ? 0 : i + 1;
  162. }
  163.  
  164. int FidoMsgWriteText(char *text, unsigned long n, unsigned long mlen)
  165. {
  166.     char i = 0;
  167.  
  168.     unused(n);
  169.     unused(mlen);
  170.  
  171.     if (text == NULL)
  172.     {
  173.         write(fp, &i, sizeof(char));
  174.         return (TRUE);
  175.     }
  176.     write(fp, text, strlen(text));
  177.     return TRUE;
  178. }
  179.  
  180. int FidoMsgWriteHeader(msg * m, int type)
  181. {
  182.     MFIDO msghead;
  183.     static char path[PATHLEN];
  184.     time_t now = time(NULL);
  185.     unsigned long n = m->msgnum;
  186.     int done = 0;
  187.     unsigned long x;
  188.  
  189.     if (fp != -1)
  190.     {
  191.         close(fp);
  192.         fp = -1;
  193.     }
  194.     sprintf(path, "%s/%lu.msg", CurArea.path, n);
  195.     if (m->new)
  196.     {
  197.         while (!done)
  198.         {
  199.             if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) != -1)
  200.             {
  201.                 close(fp);
  202.                 fp = -1;
  203.                 n++;
  204.             }
  205.             else
  206.             {
  207.                 if ((fp = sopen(path, OPENC, SH_DENYNO, S_IMODE)) == -1)
  208.                     return (ERR_OPEN_MSG);
  209.  
  210.                 done = 1;
  211.             }
  212.             sprintf(path, "%s/%lu.msg", CurArea.path, n);
  213.         }
  214.     }
  215.     else
  216.     {
  217.         if ((fp = sopen(path, OPENRW, SH_DENYNO, S_IMODE)) == -1)
  218.             return (ERR_OPEN_MSG);
  219.     }
  220.  
  221.     if (m->new)
  222.     {
  223.         if ((++msgarrsz) > oldsz)
  224.         {
  225.             unsigned long *t;
  226.  
  227.             t = xcalloc(1, (size_t) ((oldsz += CHUNKSZ) * sizeof *t));
  228.  
  229.             memcpy(t, msgarr, (size_t) (sizeof(unsigned long) * msgarrsz));
  230.             release(msgarr);
  231.             msgarr = t;
  232.         }
  233.         msgarr[(size_t) (msgarrsz - 1)] = n;
  234.     }
  235.     memset(&msghead, 0, sizeof msghead);
  236.  
  237.     m->msgnum = n;
  238.  
  239.     msghead.attrib[0] = (unsigned char)
  240.         ((m->attrib.killsent << 7)
  241.          | (m->attrib.orphan << 6)
  242.          | (m->attrib.forward << 5)
  243.          | (m->attrib.attach << 4)
  244.          | (m->attrib.sent << 3)
  245.          | (m->attrib.rcvd << 2)
  246.          | (m->attrib.crash << 1)
  247.          | (m->attrib.priv));
  248.  
  249.     msghead.attrib[1] = (unsigned char)
  250.         ((m->attrib.ureq << 7)
  251.          | (m->attrib.areq << 6)
  252.          | (m->attrib.rcpt << 5)
  253.          | (m->attrib.rreq << 4)
  254.          | (m->attrib.freq << 3)
  255.          | (m->attrib.direct << 2)
  256.          | (m->attrib.hold << 1)
  257.          | (m->attrib.local));
  258.  
  259.     x = FidoMsgnToUid((unsigned long)m->replyto);
  260.     msghead.reply[0] = (unsigned char)(x & 0xff);
  261.     msghead.reply[1] = (unsigned char)((x >> 8) & 0xff);
  262.     x = FidoMsgnToUid((unsigned long)m->replies[0]);
  263.     msghead.up[0] = (unsigned char)(x & 0xff);
  264.     msghead.up[1] = (unsigned char)((x >> 8) & 0xff);
  265.     msghead.times[0] = (unsigned char)(m->times_read & 0xff);
  266.     msghead.times[1] = (unsigned char)((m->times_read >> 8) & 0xff);
  267.     msghead.cost[0] = (unsigned char)(m->cost & 0xff);
  268.     msghead.cost[1] = (unsigned char)((m->cost >> 8) & 0xff);
  269.  
  270.     msghead.dest_net[0] = (unsigned char)(m->to.net & 0xff);
  271.     msghead.dest_net[1] = (unsigned char)((m->to.net >> 8) & 0xff);
  272.     msghead.dest[0] = (unsigned char)(m->to.node & 0xff);
  273.     msghead.dest[1] = (unsigned char)((m->to.node >> 8) & 0xff);
  274.  
  275.     if (m->isfrom != NULL)
  276.     {
  277.         size_t len_from;
  278.  
  279.         len_from = strlen(m->isfrom);
  280.         memcpy(msghead.from,
  281.                m->isfrom,
  282.                min(sizeof msghead.from, len_from));
  283.     }
  284.     else
  285.     {
  286.         msghead.from[0] = '\0';
  287.     }
  288.     if (m->isto != NULL)
  289.     {
  290.         size_t len_to;
  291.  
  292.         le